
//#include <fuse.h>
#include <stdio.h>
#include <stdint.h>//uintN_t N bits, http://linux.die.net/man/3/uint32_t
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>//manejar errores
#include <unistd.h>
#include <fcntl.h>//posix manejar archivos
#include <dirent.h>//posix manejar directorios
#include <sys/stat.h>
#include "operacionesSectores.h"
#include "estructuras.h"
//#include "operacionesFUSE.h"
#include "imprimir.h"
#include "funcionesBasicas.h"
#include "utils.h"
#include "entriesLFN.h"
#include "capaDireccionamiento.h"
#include <malloc.h>

//****************************************************************************************************

void agregarClusterALista(uint32_t nroCluster, PtrListaClusters *lista){

        PtrListaClusters punteroNuevoNodo;
        PtrListaClusters ptrPosicionLista;//se utiliza para guardar la posicion del nodo siguiente al agregar
        PtrListaClusters ptrAnteriorLista;//se utiliza para guardar la posicion del nodo anterior al agregar

        punteroNuevoNodo = malloc(sizeof(NodoListaClusters));

        if (punteroNuevoNodo != NULL){

                punteroNuevoNodo->cluster = nroCluster;
                punteroNuevoNodo->clusterSgte = NULL;
                ptrPosicionLista = *lista;
                ptrAnteriorLista = NULL;

                while ((ptrPosicionLista != NULL) && (ptrPosicionLista->cluster > nroCluster)){

                        ptrAnteriorLista = ptrPosicionLista;
                        ptrPosicionLista = ptrPosicionLista->clusterSgte;
                }

                if (ptrAnteriorLista == NULL){
                        punteroNuevoNodo->clusterSgte = *lista;
                        *lista = punteroNuevoNodo;
                }
                else { ptrAnteriorLista->clusterSgte = punteroNuevoNodo;
                                punteroNuevoNodo->clusterSgte = ptrAnteriorLista;
                }
        }
        else { printf("No hay memoria disponible!");}
        return;
}



void agregarClusterACadena(uint32_t nroCluster, PtrListaClusters *cadena){

        PtrListaClusters punteroNuevoNodo;
        PtrListaClusters ptrPosicionCadena;

        punteroNuevoNodo = malloc(sizeof(NodoListaClusters));

        if (punteroNuevoNodo != NULL){

                punteroNuevoNodo->cluster = nroCluster;
                punteroNuevoNodo->clusterSgte = NULL;
                ptrPosicionCadena = *cadena;

                if (ptrPosicionCadena == NULL){
                		*cadena = punteroNuevoNodo;
                } else {

                		while (ptrPosicionCadena->clusterSgte != NULL){
                				ptrPosicionCadena = ptrPosicionCadena->clusterSgte;
                		}

                		if (ptrPosicionCadena->clusterSgte == NULL){
                				ptrPosicionCadena->clusterSgte = punteroNuevoNodo;
                		}
                }
        } else { printf("No hay memoria disponible!");}
}

void agregarVariosClustersACadena(PtrListaClusters *cadena, PtrListaClusters *listaClusters){

		PtrListaClusters ptrPosicionCadena;
		PtrListaClusters ptrPosicionAnterior = NULL;

		ptrPosicionCadena = *cadena;

		while (ptrPosicionCadena != NULL){
			ptrPosicionAnterior = ptrPosicionCadena;
			ptrPosicionCadena = ptrPosicionCadena->clusterSgte;
		}

		if(ptrPosicionAnterior == NULL){
			*cadena = *listaClusters;
		}

		if((ptrPosicionCadena == NULL)&&(ptrPosicionAnterior != NULL)){
			ptrPosicionAnterior->clusterSgte = *listaClusters;
		}

}

void removerClusterEnCadena(uint32_t nroCluster, PtrListaClusters *cadena){

		PtrListaClusters ptrPosicionCadena;
		PtrListaClusters ptrAnteriorCadena = NULL;
		ptrPosicionCadena = *cadena;

		while ((ptrPosicionCadena != NULL)&&(ptrPosicionCadena->cluster != nroCluster)){
				ptrAnteriorCadena = ptrPosicionCadena;
				ptrPosicionCadena = ptrPosicionCadena->clusterSgte;
		}

		if (ptrPosicionCadena == NULL) {printf("\nNada que remover\n");}
		else {
				if (ptrAnteriorCadena != NULL){ptrAnteriorCadena->clusterSgte = ptrPosicionCadena->clusterSgte;}
				else {*cadena = ptrPosicionCadena->clusterSgte;}
				free(ptrPosicionCadena);
		}
}

void removerVariosClustersDeCadena(PtrListaClusters *cadena, PtrListaClusters *listaClusters){

		PtrListaClusters ptrPosicionLista;

		ptrPosicionLista = *listaClusters;

		while(ptrPosicionLista != NULL){

			removerClusterEnCadena(ptrPosicionLista->cluster,cadena);
			ptrPosicionLista = ptrPosicionLista->clusterSgte;
		}

}

uint32_t obtenerClustersLibres (){

		uint32_t indiceBitmap;

		for( indiceBitmap = 0; indiceBitmap < LONGITUD_TABLA_FAT; indiceBitmap++){

			if (vectorBitMap.bitmap[indiceBitmap] == 0){
				printf("%d\n",indiceBitmap);
				return indiceBitmap;
			}
		}
		return 0;
}

uint32_t obtenerDireccionCluster (uint32_t nroCluster){

        if( (nroCluster == 0) || (nroCluster == 1)){printf("\nClusters reservados por fat\n");return 0;}
		uint32_t direccionCluster = RESERVED_SECTOR_COUNT + (NUMBER_OF_FATS * SECTORS_PER_FAT) + ((nroCluster - 2)*SIZE_CLUSTER);
        return direccionCluster;
}

Cluster obtenerContenidoCluster (uint32_t nroCluster){

        Cluster cluster;

        if (nroCluster < 2){perror("numero de cluster no válido");exit(-5);}

        uint32_t nroBloque = convertirClusterAbloque(nroCluster);
        capaDeDireccionamientoAsectoresLectura(nroBloque);
        for( uint16_t nroSector = 0; nroSector < SIZE_BLOCK; nroSector++){
        	cluster.sectores[nroSector] = capaDir.sectores[nroSector];
        }

        return cluster;
}

void leerEntradaDataRegionPorCluster(uint32_t nroCluster){//NO SE UTILIZA

		Cluster cluster = obtenerContenidoCluster(nroCluster);
		uint16_t nroSector;
		uint32_t offset;

		for (nroSector = 0; nroSector < SIZE_CLUSTER; nroSector++){

			uint32_t numByte = 0;

			for( uint32_t nroEntrada = 0; nroEntrada < 16; nroEntrada++){

				uint8_t buffer[32];
				memcpy(buffer,&cluster.sectores[nroSector].bytes[numByte],32);
		        numByte = numByte + 32;

				offset = 0;
				if (buffer[offset] == 0x00) {printf("\nEntrada libre\n");}
				if (buffer[offset] == 46) {printf("\nDot entry\n");}

				offset = 13;//0x0B;
				//if (buffer[offset] == 0x0F) {printf("\nLFN\n"); imprimirLFN(buffer);}
				if (buffer[offset] == 0x10) {printf("\nSubdirectorio\n"); }//leerContenidoDirectorio(&buffer);}
				if (buffer[offset] == 0x20) {printf("\nArchivo\n");}
			}
		}
}

void leerEntradaDataRegionPorClusterSubdirectorio(uint32_t nroCluster){//NO SE UTILIZA

		Cluster cluster = obtenerContenidoCluster(nroCluster);
		uint16_t nroSector;
		uint32_t offset;

		for (nroSector = 0; nroSector < SIZE_CLUSTER; nroSector++){

			uint32_t numByte = 0;
			uint8_t *bufferLFN;
			uint32_t nroEntradaLFN;

			for( uint32_t nroEntrada = 0; nroEntrada < 15; nroEntrada++){

				uint8_t buffer[32];
				memcpy(&buffer,&cluster.sectores[nroSector].bytes[numByte],32);
		        numByte = numByte + 32;
				offset = 13;//0x0B;
				if( buffer[offset] == 0x0F) {bufferLFN = buffer; nroEntradaLFN = nroEntrada;}
				if (buffer[offset] == 0x10) {
					printf("\nSubdirectorio\n");
					//if( nroEntradaLFN == nroEntrada -1){imprimirLFN(bufferLFN);}
					//leerContenidoDirectorio(buffer);
				}
			}
		}
}

void leerEntradaDataRegionCadena(PtrListaClusters *cadena){//NO SE UTILIZA

	PtrListaClusters ptrPosicionCadena;

	ptrPosicionCadena = *cadena;

	while(ptrPosicionCadena != NULL){

		leerEntradaDataRegionPorCluster(ptrPosicionCadena->cluster);
		ptrPosicionCadena = ptrPosicionCadena->clusterSgte;
	}
}

